/*
 * This file is part of DALS - Distributed Artificial Life Simulation.
 * DALS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Foobar is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DALS.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Simulation.java
 *
 * Created on 26/08/2010, 12:12:59
 */
package genetic.view;

import genetic.Environment;
import genetic.components.Individual;
import genetic.util.DisplayImage;
import genetic.util.ImageCache;
import genetic.util.jLabelImage;
import genetic.view.MapaView;
import java.awt.ComponentOrientation;
import java.util.Observable;
import java.util.Observer;

/**
 *
 * @author romulo
 */
public class Simulation extends javax.swing.JFrame implements Observer {

    private boolean playing = false;
    private Environment environment;
    private MapaView mapaView;
    private jLabelImage picture = new jLabelImage();
    private ImageCache imageCache = ImageCache.getInstance();

    /** Creates new form Simulation */
    public Simulation() {
        environment = Environment.getInstance();
        playing = environment.isPlaying();
        initComponents();
        postInitComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanelEcossistem = new javax.swing.JPanel();
        jLabelEcossistemInfo = new javax.swing.JLabel();
        jLabelIndividuals = new javax.swing.JLabel();
        jLabelFoods = new javax.swing.JLabel();
        jLabelIndividualNumber = new javax.swing.JLabel();
        jLabelFoodNumber = new javax.swing.JLabel();
        jPanelControls = new javax.swing.JPanel();
        jButtonPlay = new javax.swing.JButton();
        jSliderSpeed = new javax.swing.JSlider();
        jLabelSpeed = new javax.swing.JLabel();
        jPanelSimulation = new javax.swing.JPanel();
        jPanelEnvironmentControls = new javax.swing.JPanel();
        jButtonDump = new javax.swing.JButton();
        jButtonAddIndividual = new javax.swing.JButton();
        jButtonAddFood = new javax.swing.JButton();
        jTextFieldAddIndividual = new javax.swing.JTextField();
        jTextFieldAddFood = new javax.swing.JTextField();
        jLabelAddIndividual = new javax.swing.JLabel();
        jLabelAddFood = new javax.swing.JLabel();
        jPanelIndividual = new javax.swing.JPanel();
        jLabelAge = new javax.swing.JLabel();
        jLabelEnergy = new javax.swing.JLabel();
        jLabelTitle = new javax.swing.JLabel();
        jLabelProle = new javax.swing.JLabel();
        jLabelChoosen = new javax.swing.JLabel();
        jLabelAgeNumber = new javax.swing.JLabel();
        jLabelEnergyNumber = new javax.swing.JLabel();
        jLabelProleNumber = new javax.swing.JLabel();
        jLabelChoosenNumber = new javax.swing.JLabel();
        jLabelSight = new javax.swing.JLabel();
        jLabelOlfactory = new javax.swing.JLabel();
        jLabelSightNumber = new javax.swing.JLabel();
        jLabelOlfactoryNumber = new javax.swing.JLabel();
        jPanelPicture = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        jPanelEcossistem.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jLabelEcossistemInfo.setText("Ecossistem data");

        jLabelIndividuals.setText("Population:");
        jLabelIndividuals.setToolTipText("Quantidade de indivíduos habitando este ecossistema.");

        jLabelFoods.setText("Foods:");
        jLabelFoods.setToolTipText("Quantidade de alimentos disponíveis neste ecossistema.");

        jLabelIndividualNumber.setText("-");

        jLabelFoodNumber.setText("-");

        javax.swing.GroupLayout jPanelEcossistemLayout = new javax.swing.GroupLayout(jPanelEcossistem);
        jPanelEcossistem.setLayout(jPanelEcossistemLayout);
        jPanelEcossistemLayout.setHorizontalGroup(
            jPanelEcossistemLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelEcossistemLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanelEcossistemLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabelEcossistemInfo)
                    .addGroup(jPanelEcossistemLayout.createSequentialGroup()
                        .addComponent(jLabelIndividuals)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jLabelIndividualNumber))
                    .addGroup(jPanelEcossistemLayout.createSequentialGroup()
                        .addComponent(jLabelFoods)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jLabelFoodNumber)))
                .addContainerGap(108, Short.MAX_VALUE))
        );
        jPanelEcossistemLayout.setVerticalGroup(
            jPanelEcossistemLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelEcossistemLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabelEcossistemInfo)
                .addGap(18, 18, 18)
                .addGroup(jPanelEcossistemLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabelIndividuals)
                    .addComponent(jLabelIndividualNumber))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanelEcossistemLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabelFoods)
                    .addComponent(jLabelFoodNumber))
                .addContainerGap(20, Short.MAX_VALUE))
        );

        jPanelControls.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jButtonPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/genetic/images/play.png"))); // NOI18N
        jButtonPlay.setText("Play");
        jButtonPlay.setMaximumSize(new java.awt.Dimension(100, 33));
        jButtonPlay.setMinimumSize(new java.awt.Dimension(100, 33));
        jButtonPlay.setPreferredSize(new java.awt.Dimension(100, 33));
        jButtonPlay.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonPlayActionPerformed(evt);
            }
        });

        jSliderSpeed.setMaximum(10);
        jSliderSpeed.setMinorTickSpacing(1);
        jSliderSpeed.setPaintTicks(true);
        jSliderSpeed.setSnapToTicks(true);
        jSliderSpeed.setValue(0);
        jSliderSpeed.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSliderSpeedStateChanged(evt);
            }
        });

        jLabelSpeed.setText("Speed");

        javax.swing.GroupLayout jPanelControlsLayout = new javax.swing.GroupLayout(jPanelControls);
        jPanelControls.setLayout(jPanelControlsLayout);
        jPanelControlsLayout.setHorizontalGroup(
            jPanelControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelControlsLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jButtonPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 119, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 374, Short.MAX_VALUE)
                .addComponent(jLabelSpeed)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSliderSpeed, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        jPanelControlsLayout.setVerticalGroup(
            jPanelControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelControlsLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanelControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(jSliderSpeed, javax.swing.GroupLayout.Alignment.LEADING, 0, 0, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanelControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(jButtonPlay, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jLabelSpeed)))
                .addContainerGap(16, Short.MAX_VALUE))
        );

        jPanelSimulation.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        javax.swing.GroupLayout jPanelSimulationLayout = new javax.swing.GroupLayout(jPanelSimulation);
        jPanelSimulation.setLayout(jPanelSimulationLayout);
        jPanelSimulationLayout.setHorizontalGroup(
            jPanelSimulationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 530, Short.MAX_VALUE)
        );
        jPanelSimulationLayout.setVerticalGroup(
            jPanelSimulationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 602, Short.MAX_VALUE)
        );

        jPanelEnvironmentControls.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jButtonDump.setText("Dump individuals");
        jButtonDump.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonDumpActionPerformed(evt);
            }
        });

        jButtonAddIndividual.setText("Add");
        jButtonAddIndividual.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonAddIndividualActionPerformed(evt);
            }
        });

        jButtonAddFood.setText("Add");
        jButtonAddFood.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonAddFoodActionPerformed(evt);
            }
        });

        jTextFieldAddIndividual.setText("5");

        jTextFieldAddFood.setText("5");

        jLabelAddIndividual.setText("Individuals");

        jLabelAddFood.setText("Foods");

        javax.swing.GroupLayout jPanelEnvironmentControlsLayout = new javax.swing.GroupLayout(jPanelEnvironmentControls);
        jPanelEnvironmentControls.setLayout(jPanelEnvironmentControlsLayout);
        jPanelEnvironmentControlsLayout.setHorizontalGroup(
            jPanelEnvironmentControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelEnvironmentControlsLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanelEnvironmentControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanelEnvironmentControlsLayout.createSequentialGroup()
                        .addGroup(jPanelEnvironmentControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabelAddIndividual)
                            .addComponent(jLabelAddFood))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanelEnvironmentControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(jTextFieldAddIndividual)
                            .addComponent(jTextFieldAddFood, javax.swing.GroupLayout.DEFAULT_SIZE, 44, Short.MAX_VALUE))
                        .addGap(6, 6, 6)
                        .addGroup(jPanelEnvironmentControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jButtonAddIndividual)
                            .addComponent(jButtonAddFood)))
                    .addComponent(jButtonDump))
                .addContainerGap(49, Short.MAX_VALUE))
        );
        jPanelEnvironmentControlsLayout.setVerticalGroup(
            jPanelEnvironmentControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelEnvironmentControlsLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jButtonDump)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanelEnvironmentControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabelAddIndividual)
                    .addComponent(jTextFieldAddIndividual, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButtonAddIndividual))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanelEnvironmentControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabelAddFood)
                    .addComponent(jTextFieldAddFood, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButtonAddFood))
                .addContainerGap(66, Short.MAX_VALUE))
        );

        jPanelIndividual.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jLabelAge.setText("Age:");
        jLabelAge.setToolTipText("Número de turnos executados por este indivíduo desde o seu nascimento.");

        jLabelEnergy.setText("Energy:");
        jLabelEnergy.setToolTipText("Pontos de energia restantes.");

        jLabelTitle.setText("Individual data");

        jLabelProle.setText("Father:");
        jLabelProle.setToolTipText("Quantidade de vezes que este indivíduo escolheu um parceiro para reproduzir.");

        jLabelChoosen.setText("Mother:");
        jLabelChoosen.setToolTipText("Quantidade de vezes que este indivíduo foi escolhido para reprodução.");

        jLabelAgeNumber.setText("-");

        jLabelEnergyNumber.setText("-");

        jLabelProleNumber.setText("-");

        jLabelChoosenNumber.setText("-");

        jLabelSight.setText("Sight range");
        jLabelSight.setToolTipText("Raio de alcance da visão.");

        jLabelOlfactory.setText("Olfactory:");
        jLabelOlfactory.setToolTipText("Raio de alcance do alfato.");

        jLabelSightNumber.setText("-");

        jLabelOlfactoryNumber.setText("-");

        jPanelPicture.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        jPanelPicture.setPreferredSize(new java.awt.Dimension(106, 106));

        javax.swing.GroupLayout jPanelPictureLayout = new javax.swing.GroupLayout(jPanelPicture);
        jPanelPicture.setLayout(jPanelPictureLayout);
        jPanelPictureLayout.setHorizontalGroup(
            jPanelPictureLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 102, Short.MAX_VALUE)
        );
        jPanelPictureLayout.setVerticalGroup(
            jPanelPictureLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 102, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout jPanelIndividualLayout = new javax.swing.GroupLayout(jPanelIndividual);
        jPanelIndividual.setLayout(jPanelIndividualLayout);
        jPanelIndividualLayout.setHorizontalGroup(
            jPanelIndividualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelIndividualLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanelIndividualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabelTitle)
                    .addGroup(jPanelIndividualLayout.createSequentialGroup()
                        .addGroup(jPanelIndividualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanelIndividualLayout.createSequentialGroup()
                                .addComponent(jLabelAge)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jLabelAgeNumber))
                            .addGroup(jPanelIndividualLayout.createSequentialGroup()
                                .addComponent(jLabelEnergy)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jLabelEnergyNumber))
                            .addGroup(jPanelIndividualLayout.createSequentialGroup()
                                .addComponent(jLabelProle)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jLabelProleNumber))
                            .addGroup(jPanelIndividualLayout.createSequentialGroup()
                                .addComponent(jLabelChoosen)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jLabelChoosenNumber)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 29, Short.MAX_VALUE)
                        .addComponent(jPanelPicture, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanelIndividualLayout.createSequentialGroup()
                        .addComponent(jLabelSight)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jLabelSightNumber))
                    .addGroup(jPanelIndividualLayout.createSequentialGroup()
                        .addComponent(jLabelOlfactory)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jLabelOlfactoryNumber)))
                .addContainerGap())
        );
        jPanelIndividualLayout.setVerticalGroup(
            jPanelIndividualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelIndividualLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabelTitle)
                .addGap(18, 18, 18)
                .addGroup(jPanelIndividualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanelIndividualLayout.createSequentialGroup()
                        .addGroup(jPanelIndividualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabelAge)
                            .addComponent(jLabelAgeNumber))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(jPanelIndividualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabelEnergy)
                            .addComponent(jLabelEnergyNumber))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(jPanelIndividualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabelProle)
                            .addComponent(jLabelProleNumber))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(jPanelIndividualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabelChoosen)
                            .addComponent(jLabelChoosenNumber))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(jPanelIndividualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabelSight)
                            .addComponent(jLabelSightNumber))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(jPanelIndividualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabelOlfactory)
                            .addComponent(jLabelOlfactoryNumber)))
                    .addComponent(jPanelPicture, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(58, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanelControls, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(jPanelSimulation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jPanelIndividual, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jPanelEcossistem, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jPanelEnvironmentControls, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanelControls, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanelEnvironmentControls, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jPanelEcossistem, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jPanelIndividual, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addComponent(jPanelSimulation, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void postInitComponents() {
        mapaView = new MapaView();
        mapaView.setLocation(2, 2);
        mapaView.setSize(490, 490);
        jPanelSimulation.add(mapaView);
        applySliderValueToEnvironmentSpeed();

        mapaView.addObserver(this);
        environment.addObserver(this);

        jPanelPicture.add(picture);
        picture.setSize(106, 106);

        buttonPlayPauseUpdate();
    }

    private void jButtonPlayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonPlayActionPerformed
        if (playing) {
            simulationPause();
        } else {
            simulationPlay();
        }
    }//GEN-LAST:event_jButtonPlayActionPerformed

    private void jSliderSpeedStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSliderSpeedStateChanged
        applySliderValueToEnvironmentSpeed();
    }//GEN-LAST:event_jSliderSpeedStateChanged

    private void applySliderValueToEnvironmentSpeed() {
        environment.setTimeSpeed(calculateSpeedMultiplier(jSliderSpeed.getMaximum(), jSliderSpeed.getMinimum(), jSliderSpeed.getValue()));
    }

    private float calculateSpeedMultiplier(float maxVal, float minVal, float value) {
        return maxVal - minVal - value - minVal + 1;
    }

    private void jButtonDumpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonDumpActionPerformed
        environment.dump();
    }//GEN-LAST:event_jButtonDumpActionPerformed

    private void jButtonAddIndividualActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonAddIndividualActionPerformed
        try {
            int amount = Integer.parseInt(jTextFieldAddIndividual.getText());
            environment.createIndividual(amount);
            repaint();
        } catch (NumberFormatException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }//GEN-LAST:event_jButtonAddIndividualActionPerformed

    private void jButtonAddFoodActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonAddFoodActionPerformed
        try {
            int amount = Integer.parseInt(jTextFieldAddFood.getText());
            environment.createFood(amount);
            repaint();
        } catch (NumberFormatException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }//GEN-LAST:event_jButtonAddFoodActionPerformed

    /**
     * Pauses the simulation by calling environment.pause
     */
    private void simulationPause() {
        if (playing) {
            environment.pause();
        }
        playing = false;
        buttonPlayPauseUpdate();
    }

    private void buttonPlayPauseUpdate() {
        if (playing) {
            jButtonPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/genetic/images/pause.png")));
            jButtonPlay.setText("Pause");
        } else {
            jButtonPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/genetic/images/play.png")));
            jButtonPlay.setText("Play");
        }
    }

    /**
     * Plays the simulation by calling environment.play
     */
    private void simulationPlay() {
        if (!playing) {
            environment.play();
        }
        playing = true;
        buttonPlayPauseUpdate();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new Simulation().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButtonAddFood;
    private javax.swing.JButton jButtonAddIndividual;
    private javax.swing.JButton jButtonDump;
    private javax.swing.JButton jButtonPlay;
    private javax.swing.JLabel jLabelAddFood;
    private javax.swing.JLabel jLabelAddIndividual;
    private javax.swing.JLabel jLabelAge;
    private javax.swing.JLabel jLabelAgeNumber;
    private javax.swing.JLabel jLabelChoosen;
    private javax.swing.JLabel jLabelChoosenNumber;
    private javax.swing.JLabel jLabelEcossistemInfo;
    private javax.swing.JLabel jLabelEnergy;
    private javax.swing.JLabel jLabelEnergyNumber;
    private javax.swing.JLabel jLabelFoodNumber;
    private javax.swing.JLabel jLabelFoods;
    private javax.swing.JLabel jLabelIndividualNumber;
    private javax.swing.JLabel jLabelIndividuals;
    private javax.swing.JLabel jLabelOlfactory;
    private javax.swing.JLabel jLabelOlfactoryNumber;
    private javax.swing.JLabel jLabelProle;
    private javax.swing.JLabel jLabelProleNumber;
    private javax.swing.JLabel jLabelSight;
    private javax.swing.JLabel jLabelSightNumber;
    private javax.swing.JLabel jLabelSpeed;
    private javax.swing.JLabel jLabelTitle;
    private javax.swing.JPanel jPanelControls;
    private javax.swing.JPanel jPanelEcossistem;
    private javax.swing.JPanel jPanelEnvironmentControls;
    private javax.swing.JPanel jPanelIndividual;
    private javax.swing.JPanel jPanelPicture;
    private javax.swing.JPanel jPanelSimulation;
    private javax.swing.JSlider jSliderSpeed;
    private javax.swing.JTextField jTextFieldAddFood;
    private javax.swing.JTextField jTextFieldAddIndividual;
    // End of variables declaration//GEN-END:variables

    /**
     * Process an Observable update
     * @param o
     * @param arg
     */
    public void update(Observable o, Object arg) {
        jLabelIndividualNumber.setText(environment.getIndividualCount() + "");
        jLabelFoodNumber.setText(environment.getFoodCount() + "");
        if (Individual.class.isInstance(arg)) {
            updateSelectedIndividualPanel((Individual) arg);
        }
        mapaView.repaint();
    }

    /**
     * Updates the individual detail panel with the selected individual information
     * @param individual
     */
    public void updateSelectedIndividualPanel(Individual individual) {
        jLabelAgeNumber.setText(individual.getAge() + "");
        jLabelEnergyNumber.setText(individual.getEnergy() + "");
        jLabelProleNumber.setText(individual.getChildrens() + "");
        jLabelChoosenNumber.setText(individual.getSelectedAsPartner() + "");
        jLabelSightNumber.setText(individual.getSightRange() + "");
        jLabelOlfactoryNumber.setText(individual.getOlfactoryRange() + "");
        picture.setImage(imageCache.getResized(DisplayImage.getFullPathName(individual.getImageName()), picture.getWidth(), picture.getHeight()));
        picture.repaint();
    }
}
